using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data.Linq;
using System.Reflection;
using System.Text;
using System.Web;
using System.Diagnostics;
using System.Web.Mail;
using RecruitmentAgency.Models.DataTypes;


namespace RecruitmentAgency.Models.DataProviders
{
    /// <summary>
    /// Provides database access for Exception data
    /// </summary>
    public class ExceptionDataProvider : IExceptionDataProvider
    {
        private static readonly bool LogExceptions = Convert.ToBoolean(ConfigurationManager.AppSettings["LogExceptions"]);
       
        /// <summary>
        /// Redister the dara regarding the Exception occurred in the database
        /// </summary>
        /// <param name="ex">Contains all the information of the Exception occurred</param>
        public void HandleException(Exception ex)
        {
            // if web.config setting to false, abort
            if (!LogExceptions)
            {
                return;
            }
            HttpContext ctx = HttpContext.Current;

            string appName = Environment.MachineName + "_" + Assembly.GetCallingAssembly().FullName;

            string appPath = ctx.Request.PhysicalApplicationPath;

            string referer = String.Empty;
            if (ctx.Request.ServerVariables["HTTP_REFERER"] != null)
            {
                referer = ctx.Request.ServerVariables["HTTP_REFERER"];
            }

            string sForm = (ctx.Request.Form != null) ? ctx.Request.Form.ToString() : String.Empty;

            string data = "";
            StringBuilder sb = new StringBuilder();
            if (ex.Data.Count > 0)
            {
                foreach (object key in ex.Data.Keys)
                {
                    sb.Append((string)key);
                    sb.Append("=");
                    sb.Append((string)ex.Data[key]);
                    sb.Append("|");
                }
                sb.Remove(sb.Length - 1, 1);
                data = sb.ToString();
            }

            DateTime logDateTime = DateTime.Now;
            string sQuery = (ctx.Request.QueryString != null) ? ctx.Request.QueryString.ToString() : String.Empty;

            string strData = "\nSOURCE: " + ex.Source +
                             "\nAppName: " + appName +
                             "\nLogDateTime: " + logDateTime +
                             "\nMESSAGE: " + ex.Message +
                             "\nFORM: " + sForm +
                             "\nQUERYSTRING: " + sQuery +
                             "\nTARGETSITE: " + ex.TargetSite +
                             "\nSTACKTRACE: " + ex.StackTrace +
                             "\nREFERER: " + referer +
                             "\nDATA: " + data +
                             "\nPath: " + appPath;

       
            //// Get data context
            RecruitmentDatabaseDataContext mdldc = new RecruitmentDatabaseDataContext();
            if (ex.StackTrace != null) mdldc.up_ExceptionLogsInsert(appName, logDateTime, ex.Source, ex.Message, sQuery, ex.TargetSite.ToString(),ex.StackTrace, ex.StackTrace, referer, data, appPath);
           
            string strEmails = ConfigurationManager.AppSettings["emailAddresses"];
            if (strEmails.Length > 0)
            {
                try
                {
                    string[] emails = strEmails.Split(Convert.ToChar(";"));
                    string fromEmail = ConfigurationManager.AppSettings["fromEmail"];
                    string subject = "Web application error on " + Environment.MachineName;
                    string detailUrl = ConfigurationManager.AppSettings["detailURL"];
                    string fullMessage = strData + detailUrl;
                    string smtpServer = ConfigurationManager.AppSettings["smtpServer"];
                    string ccs = String.Join(";", emails, 1, emails.Length - 1);
                    MailMessage msg = new MailMessage();
                    msg.To = emails[0];
                    msg.From = fromEmail;
                    msg.Cc = ccs;
                    msg.Body = fullMessage;
                    msg.Subject = subject;
                    SmtpMail.SmtpServer = smtpServer;
                    SmtpMail.Send(msg);
                }
                catch (Exception excm)
                {
                    Debug.WriteLine(excm.Message);
                }
            }
        }

        /// <summary>
        /// Returns a list of exceptions according to the parameters specified
        /// </summary>
        /// <param name="applName">The application where the Exception occurred</param>
        /// <param name="beginDate">The starting date for the exception search</param>
        /// <param name="endDate">The end date for the exception search</param>
        /// <param name="msg">The message contained in the Exception</param>
        /// <param name="targetSite">The target site where the Exception occurred</param>
        /// <param name="refer">The referral page respect where the Exception occurred</param>
        /// <param name="exceptionPath">The application path of the Exception</param>
        /// <returns>Returns a list of Exceptions</returns>
        public List<ExceptionLog> SearchExceptions(string applName, DateTime? beginDate, DateTime? endDate, string msg, string targetSite, string refer, string exceptionPath)
        {
            List<ExceptionLog> exceptionList = new List<ExceptionLog>();

            string applicationName = !string.IsNullOrEmpty(applName) ? applName : null;
            string message = !string.IsNullOrEmpty(msg) ? msg : null;
            string site = !string.IsNullOrEmpty(targetSite) ? targetSite : null;
            string referrer = !string.IsNullOrEmpty(refer) ? refer : null;
            string path = !string.IsNullOrEmpty(exceptionPath) ? exceptionPath : null;

            try
            {
                //get data Context
                RecruitmentDatabaseDataContext rddc = new RecruitmentDatabaseDataContext();
                ISingleResult<up_SearchExceptionLogResult> result = rddc.up_SearchExceptionLog(applicationName, beginDate, endDate, message, site, referrer, path);

                foreach (up_SearchExceptionLogResult se in result)
                {
                    ExceptionLog exception = new ExceptionLog
                                                 {
                                                     ApplicationName = se.AppName,
                                                     ApplicationPath = se.Path,
                                                     Data = se.Data,
                                                     DateTime = (DateTime)se.LogDateTime,
                                                     Form = se.Form,
                                                     Message = se.Message,
                                                     Query = se.QueryString,
                                                     Referrer = se.Referer,
                                                     Source = se.Source,
                                                     StackTrace = se.StackTrace
                                                 };
                    exception.Target = exception.Target;

                    exceptionList.Add(exception);
                }
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
            return exceptionList;
        }

        /// <summary>
        /// Delete all the exception from the exception log table
        /// </summary>
        /// <returns>Returns zero if the delete was successfully</returns>
        public int DeleteAllExceptions()
        {
            int result = 0;
            try
            {
                //get data Context
                RecruitmentDatabaseDataContext rddc = new RecruitmentDatabaseDataContext();
                result = rddc.up_DeleteException_All();

            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
            return result;
        }
    }
}